﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using SDT.DataService.Services;
using SDT.DataService;


namespace SDT.Libraries.DuplicateDetection
{
   public sealed class DuplicateDetector
   {
       #region variables
       public int ngram = 1;
        public Article ArtObj { get; set; }
        public int ArtID
        {
            get;
            set;
        }
        public string InputString
        {
            get;
            set;
        }
        public double StandardRate
        {
            get;
            set;
        }
        public int NGram
        {
            get;
            set;
        }
       #endregion

       #region constructor
        public DuplicateDetector(int artID, string inputString, double standardRate,int nGram)
        {
            this.ArtID = artID;
            this.InputString = inputString;
            this.StandardRate = standardRate;
            this.NGram = ngram;

        }
        #endregion

        public void ProcessDuplicateDetector()
        {
            try
            {
                ngram = this.NGram;
                //Get Article that this Article duplicate with it
                ArtObj = GetArticleOne(this.ArtID, this.InputString, this.StandardRate);
                //Update DB
                if (ArtObj != null)
                    UpdateDuplicatedArticle(ArtObj.ArticleID, ArtObj.OtherArticleID, ArtObj.Rate);
            }
            catch { }

        }

    
       
        public double Detect(string page1, string page2)
        {   
            //string
            List<string> s1 = CreateShingle(page1);
            List<string> s2 = CreateShingle(page2);

            var commonelements = s1.Intersect(s2);
            var totalElements = s1.Union(s2);

            double jaccardCoef = (Convert.ToDouble(commonelements.Count())) / (Convert.ToDouble(totalElements.Count()));

            return jaccardCoef;
        }
     
        public List<string> CreateShingle(string content)
        {
            Helper hp = new Helper();

            List<string> nGrams = new List<string>();
            List<string> nGramsMD5 = new List<string>();

            string[] words = Regex.Split(content, @"\W", RegexOptions.IgnoreCase);
            words = hp.RemoveEmptyString(words);

            for (int i = 0; i < words.Length; i++)
            {
                string shingle = words[i];

                for (int j = 1; j < ngram; j++)
                {
                    if ((i + j) < words.Length)
                    {
                        shingle += " " + words[i + j];
                    }
                    else
                    {
                        shingle = "";
                        break;
                    }
                }
                if (!string.IsNullOrEmpty(shingle))
                {
                    nGrams.Add(shingle);
                    nGramsMD5.Add(hp.CalculateMD5Hash(shingle));
                }

            }

            return nGramsMD5;

        }       
       
        #region Code       

        private IList<IDetect> GetDuplicatedList(string inputString, IList<IArticle> List)
        {
            IList<IDetect> list = new List<IDetect>();

            foreach (var obj in List)
            {
                double rate = Detect(inputString, obj.Title + " " + obj.Sumary) * 100;
                IDetect detect = new Detect(obj.OtherArticleID, obj.Dt, rate);
                list.Add(detect);
            }
            return list;
        }


        private Article GetArticleFromDetectList(int ArtID, IList<IDetect> DetectList, double standardRate)
        {
            IDetect deObj = null;
            deObj = DetectList.Where(itm => itm.Rate > standardRate).OrderBy(itm => itm.Date).FirstOrDefault();
            if (deObj != null)
                return new Article(ArtID, (Detect)deObj);

            return null;

        }

        private Article GetArticleOne(int ArtID, string inputString, double standardRate)
        {
            //convert into list Article from DB
            List<IArticle> List = ConvertArticleList(ArtID);
            //Process compare return list result
            IList<IDetect> listDetect = GetDuplicatedList(inputString, List);
            //Get one result
            return GetArticleFromDetectList(ArtID, listDetect, standardRate);
        }
       /// <summary>
       /// Get List previous Article
       /// </summary>
       /// <param name="ArtID"></param>
       /// <returns></returns>
        private List<IArticle> ConvertArticleList(int ArtID)
        {
            List<IArticle> List = new List<IArticle>();
            var listArticle = (new NewsService()).GetPreviousArticle(ArtID).ToList();

            foreach (var itm in listArticle)
            { 
              List.Add(new Article(ArtID, (int)itm.ArticleID,itm.title,itm.Summary,itm.AddDate));  
            }
            return List;      
          
        }

        private int UpdateDuplicatedArticle(int DuplicatedArticleID, int ArticleID, double rate)
        {
             return (new NewsService()).DuplicatedArticleInsert(DuplicatedArticleID,ArticleID,rate);
        }


        #endregion
       
      
   
   }
}
